package springboot.tool;

import lombok.extern.slf4j.Slf4j;
import org.opentcs.access.KernelServicePortal;
import org.opentcs.access.rmi.KernelServicePortalBuilder;
import org.opentcs.access.to.order.DestinationCreationTO;
import org.opentcs.access.to.order.OrderSequenceCreationTO;
import org.opentcs.access.to.order.TransportOrderCreationTO;
import org.opentcs.components.kernel.services.DispatcherService;
import org.opentcs.components.kernel.services.TransportOrderService;
import org.opentcs.components.kernel.services.VehicleService;
import org.opentcs.data.TCSObjectReference;
import org.opentcs.data.model.Point;
import org.opentcs.data.model.Vehicle;
import org.opentcs.data.order.OrderSequence;
import org.opentcs.data.order.TransportOrder;
import org.opentcs.drivers.vehicle.LoadHandlingDevice;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
import springboot.bean.Taskzc;

import java.util.*;

@Slf4j
//如果是注解的@Component 这样搞成单例模式,多线程操作，成员变量会有线程安全问题
//@Scope("")搞成多例,那么注入只会注入一次,除非将service也搞成多例,那样更不好,直接在service里new三个对象得了
public class KernelTools {
    private KernelServicePortal kernel=null;
    private TransportOrderService orderService=null;
    private VehicleService vservice=null;
    private Vehicle vehicle=null;
    private DispatcherService dispatcherService=null;
    private TransportOrder TO=null;
    private TransportOrderCreationTO orderTO=null;
    //依据车名称来立即取消订单任务
    public void withdrawOrder(String vehiclename) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();//获得调度服务
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        dispatcherService = kernel.getDispatcherService();//获得调度服务
        dispatcherService.withdrawByVehicle(vehicle.getReference(), true);//撤销任务
        kernel.logout();
    }
    public TransportOrder getTO(String ordername){
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();
        TO = orderService.fetchObject(TransportOrder.class, ordername);
        kernel.logout();
        return TO;
    }

    public String getOrderStatus(String ordername) {
        String tos = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            orderService = kernel.getTransportOrderService();//获得调度服务
            TO = orderService.fetchObject(TransportOrder.class, ordername);//用调度服务以及调度名称来获得对应的调度任务
            tos = TO.getState().name();//依据调度任务来获得该任务的状态名称
            kernel.logout();
        } catch (Exception e) {
            log.info("My getOrderStatus:{} error:{}", ordername, e);
        }
        return tos;
    }

    public String getProcState(String vehiclename) {
        String procstate="NO";
        try{
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        procstate = vehicle.getProcState().name();
        kernel.logout();
        }catch (Exception e){
            throw e;
        }
        return procstate;
    }

    public String getVehicleStatus(String vehiclename) {
        String vs="NO";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            vs= vehicle.getState().name();
            kernel.logout();
        }catch (Exception e){
            throw e;
        }
        return vs;
    }

    public String getVehiclelevel(String vehiclename) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        String ilevel = vehicle.getIntegrationLevel().name();
        kernel.logout();
        return ilevel;
    }

    //依据车名称来获得任务名称
    public String getTranspotOrder(String vehiclename) {
        String Toname = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();//获得车相关的服务
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);//获得车对象
            Toname = vehicle.getTransportOrder().getName();//获得此车对应的调度任务的名称
            kernel.logout();
        } catch (Exception e) {
            // logger.info("My getTranspotOrder error {}",e);
        }
        return Toname;
    }

    public int getCritical(String vehiclename) {
        int i = 0;
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            i = vehicle.getEnergyLevelCritical();
            kernel.logout();
        } catch (Exception e) {
            // logger.info("My getCritical error {}",e);
        }
        return i;
    }
    private int i=0;
    public int getEnergy(String vehiclename) {
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            i = vehicle.getEnergyLevel();
            kernel.logout();
        } catch (Exception e) {
            log.info("获取电量时发生异常{}",e);
        }
        return i;
    }

    public boolean isLastState(String order) {
        boolean flag = false;
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            orderService = kernel.getTransportOrderService();
            TO= orderService.fetchObject(TransportOrder.class, order);
            flag = TO.getState().isFinalState();
            kernel.logout();
        } catch (NullPointerException e) {
            log.info("My isLastState order:{} error {}", order, e);
        }
        return flag;
    }
    //获得车当前的点位
    public String getPosition(String vehiclename) {
        String position = "";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            position = vehicle.getCurrentPosition().getName();
            kernel.logout();
        } catch (Exception e) {
            log.info("My getPosition error {}", e);
        }
        return position;
    }
    //依据任务名获得唯一的主键
    public int getOrderID(String order) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();
        TO = orderService.fetchObject(TransportOrder.class, order);
        String id = TO.getProperty("OrderID");//获得对应的序列号
        kernel.logout();
        return Integer.valueOf(id);
    }

    public boolean getloadStateisfull(String vehiclename) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        if (!vehicle.getLoadHandlingDevices().isEmpty()) {
            for (LoadHandlingDevice device : vehicle.getLoadHandlingDevices()) {
                if (device.isFull()) {
                    return true;
                }
            }
        }
        return false;
    }
    //获得任务订单的操作，比如Unload-..Load-..等
    public String getDriveOrderOperation(String ordername) {
        String driveorderOperation = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            orderService = kernel.getTransportOrderService();
            TO= orderService.fetchObject(TransportOrder.class, ordername);
            driveorderOperation = TO.getCurrentDriveOrder().getDestination().getOperation();
            kernel.logout();
        } catch (Exception e) {

        }
        return driveorderOperation;
    }
    //获得任务订单的状态，比如TRAVELLING
    public String getDriveOrderState(String ordername) {
        String driveorderState = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            orderService = kernel.getTransportOrderService();
            TO= orderService.fetchObject(TransportOrder.class, ordername);
            driveorderState = TO.getCurrentDriveOrder().getState().name();
            kernel.logout();
        } catch (Exception e) {

        }
        return driveorderState;
    }

    //获得调度取放货的目标点位
    public String getDriverOrderPoint(String ordername) {
        String driverorderPoint="N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            orderService = kernel.getTransportOrderService();
            TO= orderService.fetchObject(TransportOrder.class, ordername);
            Point point=TO.getCurrentDriveOrder().getRoute().getFinalDestinationPoint();
            driverorderPoint=point.getName();
        }catch(Exception e){
            e.printStackTrace();
            log.info("error is:",e);
        }

        return driverorderPoint;
    }

    //获得正在执行的任务的站位信息
    public String getDriveOrderLocation(String ordername) {
        String driveorderState = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            orderService = kernel.getTransportOrderService();
            TO= orderService.fetchObject(TransportOrder.class, ordername);
            driveorderState = TO.getCurrentDriveOrder().getDestination().getDestination().getName();
            kernel.logout();
        } catch (Exception e) {
        }
        return driveorderState;
    }

    //获得error1信息(从AGV车中获取相关的错误信息)
    public int getError1(String vehiclename) {
        int error1 = 0;
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            error1 = Integer.valueOf(vehicle.getProperty("Error1"));
            kernel.logout();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return error1;
    }

    //获得error2信息
    public int getError2(String vehiclename) {
        int error2 = 0;
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            error2 = Integer.valueOf(vehicle.getProperty("Error2"));
            kernel.logout();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return error2;
    }
    public void CreateOrderOneStation(Taskzc taskzc) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();
        dispatcherService = kernel.getDispatcherService();
        List<DestinationCreationTO> destinations = new LinkedList();
        String source = "Location-"+taskzc.getStart();
        String sa = "Load cargo:01";
        String dest = "Location-"+taskzc.getEnd();
        String da = "Unload cargo:03";
        //将调度的数据放至数组
        destinations.add(new DestinationCreationTO(source, sa));
        destinations.add(new DestinationCreationTO(dest, da));
        //orderTO为调度任务的数据(包括任务号以及起始目的数据)
        orderTO= new TransportOrderCreationTO(taskzc.getName(), destinations);
        orderTO = orderTO.withProperty("name",taskzc.getName());
        //为调度任务的属性,将托盘号以及其它的放在任务里面(将数据信息放在调度任务里,以后可以从这个任务获取到相关的信息)
        TO = orderService.createTransportOrder(orderTO);//创建调度任务
        dispatcherService.dispatch();//调度该任务
        kernel.logout();
        log.info("下发任务成功,任务的名称={},起始位置={},终点位置={}",taskzc.getName(),taskzc.getStart(),taskzc.getEnd());
    }
    public void onlyUnload(Taskzc taskzc) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();
        dispatcherService = kernel.getDispatcherService();
        List<DestinationCreationTO> destinations = new LinkedList();
        orderTO = orderTO.withProperty("SequenceNull",taskzc.getSequence());
        orderTO = orderTO.withProperty("name",taskzc.getName());
        String dest = "Location-"+taskzc.getEnd();
        String da = "Unload cargo:01";
        destinations.add(new DestinationCreationTO(dest, da));
        orderTO = new TransportOrderCreationTO("TASK"+ UUID.randomUUID(), destinations);
        TO= orderService.createTransportOrder(orderTO);
        dispatcherService.dispatch();
        kernel.logout();
    }

    public void cancelOrder(String vehiclename) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        dispatcherService = kernel.getDispatcherService();
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        dispatcherService.withdrawByVehicle(vehicle.getReference(), true);
        kernel.logout();
    }

    public void changecategory(String vehiclename, Set<String> processableCategories) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        vservice= kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        vservice.updateVehicleProcessableCategories(vehicle.getReference(), processableCategories);
        kernel.logout();
    }

    public Set<String> getProcCategories(String vehiclename) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        kernel.logout();
        return vehicle.getProcessableCategories();
    }

    public void initChangecategory(String vehiclename, String type) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        vservice = kernel.getVehicleService();
        vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
        Set<String> procCategories = new LinkedHashSet();
        procCategories.add(type);
        vservice.updateVehicleProcessableCategories(vehicle.getReference(), procCategories);
        kernel.logout();
    }

    public String getinter(String vehiclename) {//获得该车的调用级别
        String level = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            level = vehicle.getIntegrationLevel().toString();
            kernel.logout();
        } catch (Exception e) {

        }
        return level;
    }

    public String getRequest(String vehiclename) {
        String request = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            request = vehicle.getProperty("requestUnload");//依据车设置的属性来获得对应的值
            kernel.logout();
        } catch (Exception e) {
        }
        return request;
    }
    /*这个方法是来获取车的属性对应的值*/
    public String getProperty(String vehiclename,String endKey) {
        String property = "N/A";
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            property = vehicle.getProperty(endKey);//依据车设置的属性来获得对应的值
            kernel.logout();
        } catch (Exception e) {
        }
        return property;
    }

    public void setCanUnload(String vehiclename) {
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            vservice.updateObjectProperty(vehicle.getReference(), "canUnload", "Y");//将可以放货的指令变为Y
            kernel.logout();
        } catch (Exception e) {
        }
    }

    //依据任务名获得唯一的主键
    public String getPropertyByOrder(String order,String property) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();
        TO = orderService.fetchObject(TransportOrder.class, order);
        String end = TO.getProperty(property);
        if (end==null){
            return "N/A";
        }
        kernel.logout();
        return end;
    }

    //创建一车任务序列,但并不结束任务
    private OrderSequenceCreationTO sequenceTO=null;
    private OrderSequence orderSquence=null;
    private List<DestinationCreationTO> destinations=null;
    public void CreateOrderSquenceStart(Taskzc taskzc) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();//获得订单服务
        dispatcherService = kernel.getDispatcherService();//获得调度服务
        //任务序列
        sequenceTO=new OrderSequenceCreationTO(taskzc.getSequence());
        sequenceTO=sequenceTO.withFailureFatal(true);
        orderSquence=orderService.createOrderSequence(sequenceTO);
        //此数组用来获得调度的数据
        destinations = new LinkedList();
        String source = "Location-"+taskzc.getStart();
        String sa = "Load cargo:02";
        //将调度的数据放至数组
        destinations.add(new DestinationCreationTO(source, sa));
        /*destinations.add(new DestinationCreationTO("1605",
                DriveOrder.Destination.OP_MOVE));*/
        //创建任务并把任务添加到这个任务序列中来
        TransportOrderCreationTO orderTO=
                new TransportOrderCreationTO(taskzc.getName(), destinations)
                        .withWrappingSequence(orderSquence.getName());
        orderTO = orderTO.withProperty("name",taskzc.getName());
        //创建任务
        orderService.createTransportOrder(orderTO);
        //调度任务
        dispatcherService.dispatch();
        kernel.logout();
    }

    public TCSObjectReference<OrderSequence> getOrderSequence(String vehiclename) {
        TCSObjectReference<OrderSequence> orderSequence=null ;
        try {
            kernel = new KernelServicePortalBuilder().build();
            kernel.login("localhost", 1099);
            vservice = kernel.getVehicleService();
            vehicle = vservice.fetchObject(Vehicle.class, vehiclename);
            orderSequence = vehicle.getOrderSequence();
            kernel.logout();
        } catch (Exception e) {

        }
        return orderSequence;
    }

    //插入一车任务序列,并结束任务
    //可以从车中获取，也可以从orderSquence任务序列中获取
    public void CreateOrderSquenceEnd(Taskzc taskzc,TCSObjectReference<OrderSequence> orderSquenceref) {
        kernel = new KernelServicePortalBuilder().build();//创建kernel内核服务
        kernel.login("localhost", 1099);//登录到kernel
        orderService = kernel.getTransportOrderService();//获得订单服务
        dispatcherService = kernel.getDispatcherService();//获得调度服务
        List<DestinationCreationTO> destinations = new LinkedList();
        String dest = "Location-"+taskzc.getEnd();
        String da = "Unload cargo:07";
        destinations.add(new DestinationCreationTO(dest, da));
        //创建任务并把任务添加到这个任务序列中来
        TransportOrderCreationTO orderTO=
                new TransportOrderCreationTO(taskzc.getName(),destinations)
                        .withWrappingSequence(taskzc.getSequence());
        orderTO = orderTO.withProperty("name",taskzc.getName());
        //创建任务
        orderService.createTransportOrder(orderTO);
        //标记任务序列结束
        orderService.markOrderSequenceComplete(orderSquenceref);
        //调度任务
        dispatcherService.dispatch();
        kernel.logout();
    }
    //重新发送任务时,还是采用之前的name来更新任务
    public void CreateOrderOneStationResend(Taskzc taskzc) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();
        dispatcherService = kernel.getDispatcherService();
        List<DestinationCreationTO> destinations = new LinkedList();
        String source = "Location-"+taskzc.getStart();
        String sa = "Load cargo:01";
        String dest = "Location-"+taskzc.getEnd();
        String da = "Unload cargo:03";
        //将调度的数据放至数组
        destinations.add(new DestinationCreationTO(source, sa));
        destinations.add(new DestinationCreationTO(dest, da));
        //orderTO为调度任务的数据(包括任务号以及起始目的数据)
        orderTO= new TransportOrderCreationTO("TASK-"+UUID.randomUUID().toString(), destinations);
        orderTO = orderTO.withProperty("name",taskzc.getName());
        //为调度任务的属性,将托盘号以及其它的放在任务里面(将数据信息放在调度任务里,以后可以从这个任务获取到相关的信息)
        TO = orderService.createTransportOrder(orderTO);//创建调度任务
        dispatcherService.dispatch();//调度该任务
        kernel.logout();
        log.info("下发任务成功,任务的名称={},起始位置={},终点位置={}",taskzc.getName(),taskzc.getStart(),taskzc.getEnd());
    }

    public void CreateOrderSquenceEndResend(Taskzc taskzc) {
        kernel = new KernelServicePortalBuilder().build();//创建kernel内核服务
        kernel.login("localhost", 1099);//登录到kernel
        orderService = kernel.getTransportOrderService();//获得订单服务
        dispatcherService = kernel.getDispatcherService();//获得调度服务
        if (taskzc.getCategory()==2){
            List<DestinationCreationTO> destinations = new LinkedList();
            String dest = "Location-"+taskzc.getEnd();
            String da = "Unload cargo:03";
            destinations.add(new DestinationCreationTO(dest, da));
            orderTO= new TransportOrderCreationTO("TASK-"+UUID.randomUUID().toString(), destinations);
            orderTO = orderTO.withProperty("name",taskzc.getName());
            //为调度任务的属性,将托盘号以及其它的放在任务里面(将数据信息放在调度任务里,以后可以从这个任务获取到相关的信息)
            TO = orderService.createTransportOrder(orderTO);//创建调度任务
            dispatcherService.dispatch();//调度该任务
            kernel.logout();
        }else{
            //任务序列
            sequenceTO=new OrderSequenceCreationTO(taskzc.getSequence());
            sequenceTO=sequenceTO.withFailureFatal(true);
            orderSquence=orderService.createOrderSequence(sequenceTO);
            List<DestinationCreationTO> destinations = new LinkedList();
            String dest = "Location-"+taskzc.getEnd();
            String da = "Unload cargo:07";
            destinations.add(new DestinationCreationTO(dest, da));
            //创建任务并把任务添加到这个任务序列中来
            TransportOrderCreationTO orderTO=
                    new TransportOrderCreationTO("TASK-"+UUID.randomUUID().toString(),destinations)
                            .withWrappingSequence(taskzc.getSequence());
            orderTO = orderTO.withProperty("name",taskzc.getName());
            //创建任务
            orderService.createTransportOrder(orderTO);
            //标记任务序列结束
            orderService.markOrderSequenceComplete(orderSquence.getReference());
            //调度任务
            dispatcherService.dispatch();
            kernel.logout();
        }
    }
    public void CreateOrderSquenceStartResend(Taskzc taskzc) {
        kernel = new KernelServicePortalBuilder().build();
        kernel.login("localhost", 1099);
        orderService = kernel.getTransportOrderService();//获得订单服务
        dispatcherService = kernel.getDispatcherService();//获得调度服务
        //任务序列
        sequenceTO=new OrderSequenceCreationTO(taskzc.getSequence());
        sequenceTO=sequenceTO.withFailureFatal(true);
        orderSquence=orderService.createOrderSequence(sequenceTO);
        //此数组用来获得调度的数据
        destinations = new LinkedList();
        String source = "Location-"+taskzc.getStart();
        String sa = "Load cargo:02";
        //将调度的数据放至数组
        destinations.add(new DestinationCreationTO(source, sa));
        //创建任务并把任务添加到这个任务序列中来
        TransportOrderCreationTO orderTO=
                new TransportOrderCreationTO("TASK-"+UUID.randomUUID().toString(), destinations)
                        .withWrappingSequence(orderSquence.getName());
        orderTO = orderTO.withProperty("name",taskzc.getName());
        //创建任务
        orderService.createTransportOrder(orderTO);
        //调度任务
        dispatcherService.dispatch();
        kernel.logout();
    }
}
